/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.tools;

/**
 *
 * @author YG
 */
import java.io.UnsupportedEncodingException;
import java.util.StringTokenizer;
import org.apache.log4j.Logger;

/**
 * 工具类，提供一些方便的方法
 */
public class Util {

    public static Logger log = Logger.getLogger(Util.class.getName());
    private static StringBuilder sb = new StringBuilder();

    /**
     * 从ip的字符串形式得到字节数组形式
     *
     * @param ip 字符串形式的ip
     * @return 字节数组形式的ip
     */
    public static byte[] getIpByteArrayFromString(String ip) {
        byte[] ret = new byte[4];
        StringTokenizer st = new StringTokenizer(ip, ".");
        try {
            ret[0] = (byte) (Integer.parseInt(st.nextToken()) & 0xFF);
            ret[1] = (byte) (Integer.parseInt(st.nextToken()) & 0xFF);
            ret[2] = (byte) (Integer.parseInt(st.nextToken()) & 0xFF);
            ret[3] = (byte) (Integer.parseInt(st.nextToken()) & 0xFF);
        } catch (Exception e) {
            log.error("从ip的字符串形式得到字节数组形式报错" + e, e);
        }
        return ret;
    }

    /**
     * @param ip ip的字节数组形式
     * @return 字符串形式的ip
     */
    public static String getIpStringFromBytes(byte[] ip) {
        sb.delete(0, sb.length());
        sb.append(ip[0] & 0xFF);
        sb.append('.');
        sb.append(ip[1] & 0xFF);
        sb.append('.');
        sb.append(ip[2] & 0xFF);
        sb.append('.');
        sb.append(ip[3] & 0xFF);
        return sb.toString();
    }

    /**
     * 根据某种编码方式将字节数组转换成字符串
     *
     * @param b 字节数组
     * @param offset 要转换的起始位置
     * @param len 要转换的长度
     * @param encoding 编码方式
     * @return 如果encoding不支持，返回一个缺省编码的字符串
     */
    public static String getString(byte[] b, int offset, int len, String encoding) {
        try {
            return new String(b, offset, len, encoding);
        } catch (UnsupportedEncodingException e) {
            return new String(b, offset, len);
        }
    }

    /**
     * write specfield bytes to a byte array start from offset
     *
     * @param b
     * @param offset
     * @param v
     * @param bytes
     */
    public static void write(byte[] b, int offset, long v, int bytes) {
        for (int i = 0; i < bytes; i++) {
            b[offset++] = (byte) ((v >>> (8 * i)) & 0xFF);
        }
    }

    /**
     * write a int to a byte array
     *
     * @param b
     * @param offet
     * @param v
     */
    public static void writeIntLong(byte[] b, int offset, long v) {
        b[offset++] = (byte) ((v >> 0) & 0xFF);
        b[offset++] = (byte) ((v >> 8) & 0xFF);
        b[offset++] = (byte) ((v >> 16) & 0xFF);
        b[offset] = (byte) ((v >> 24) & 0xFF);
    }

    /**
     * get a int from a byte array start from the specifiled offset
     *
     * @param b
     * @param offset
     */
    public static long getIntLong(byte[] b, int offset) {
        return (((b[offset++] & 0x000000FFL))
                | ((b[offset++] << 8) & 0x0000FF00L)
                | ((b[offset++] << 16) & 0x00FF0000L)
                | ((b[offset] << 24) & 0xFF000000L));
    }

    /**
     * get a int from a byte array start from the specifield offset
     *
     * @param b
     * @param offset
     */
    public static int getInt3(byte[] b, int offset) {
        return ((b[offset++] & 0x000000FF)
                | (b[offset++] & 0x0000FF00)
                | (b[offset] & 0x00FF0000));
    }

    public static int getInt2(byte[] b, int offset) {
        return ((b[offset++] & 0x000000FF)
                | (b[offset] & 0x0000FF00));
    }

    public static int getInt1(byte[] b, int offset) {
        return ((b[offset] & 0x000000FF));
    }

    /**
     * string ip to long ip
     *
     * @param ip
     * @return long
     */
    public static long ip2long(String ip) {
        String[] p = ip.split("\\.");
        if (p.length != 4) {
            return 0;
        }

        int p1 = ((Integer.valueOf(p[0]) << 24) & 0xFF000000);
        int p2 = ((Integer.valueOf(p[1]) << 16) & 0x00FF0000);
        int p3 = ((Integer.valueOf(p[2]) << 8) & 0x0000FF00);
        int p4 = ((Integer.valueOf(p[3]) << 0) & 0x000000FF);

        return ((p1 | p2 | p3 | p4) & 0xFFFFFFFFL);
    }

    /**
     * int to ip string
     *
     * @param ip
     * @return string
     */
    public static String long2ip(long ip) {
        StringBuilder sb = new StringBuilder();

        sb
                .append((ip >> 24) & 0xFF).append('.')
                .append((ip >> 16) & 0xFF).append('.')
                .append((ip >> 8) & 0xFF).append('.')
                .append((ip >> 0) & 0xFF);

        return sb.toString();
    }

    /**
     * check the validate of the specifeld ip address
     *
     * @param ip
     * @return boolean
     */
    public static boolean isIpAddress(String ip) {
        String[] p = ip.split("\\.");
        if (p.length != 4) {
            return false;
        }

        for (String pp : p) {
            if (pp.length() > 3) {
                return false;
            }
            int val = Integer.valueOf(pp);
            if (val > 255) {
                return false;
            }
        }

        return true;
    }
    public static void main(String[] args) {
        System.out.println(ip2long("10.136.64.30"));
        System.out.println(ip2long("10.136.64.32"));
        System.out.println(long2ip(4294967295l));
    }
}
